﻿namespace DesktopRibbon.Launcher
{
    using System;
    using System.Collections;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Diagnostics;
    using System.Net;
    using System.IO;
    using System.ComponentModel;
    using System.Windows.Threading;
    using System.Threading;
    using System.Xml.Serialization;

    /// <summary>
    /// The ShellLauncherItem launches a file or application pointed to by a path.
    /// </summary>
    [Serializable]
    public class ShellLauncherItem : LauncherItem
    {
        #region Fields

        private string path;
        private string label;
        [NonSerialized]
        private IconCache.IconCache iconCache;
        [NonSerialized]
        private bool triedReadImages = false;
        private bool labelLoaded = false;
        [NonSerialized]
        private ImageSource smallImage;
        [NonSerialized]
        private ImageSource largeImage;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes this ShellLauncherItem with the file or application found at path.
        /// </summary>
        /// <param name="iconCache">The IconCache object that this launcher uses to load it's icon.</param>
        /// <param name="path">Path to a file or application that this launcher refers to.</param>
        public ShellLauncherItem(IconCache.IconCache iconCache, string path)
        {
            this.path = path;
            this.iconCache = iconCache;
            this.iconCache.IconLoaded += IconLoadedFromCache;
        }

        protected ShellLauncherItem()
        {
        }

        #endregion

        #region Properties

        /// <summary>
        /// The full file path or URL this ShellLauncherItem will launch.
        /// </summary>
        [XmlAttribute]
        public string Path
        {
            get
            {
                return this.path;
            }
            set
            {
                this.path = value;
            }
        }

        public override string Label
        {
            get {
                if (null == label && ! labelLoaded)
                {
                    labelLoaded = true;
                    try {
                        var info = System.Diagnostics.FileVersionInfo.GetVersionInfo(path);
                        label = info.FileDescription;
                        if (label == null)
                        {
                            label = new FileInfo(path).Name;
                        }
                    } catch (Exception)
                    {
                        label = path;
                    }
                }
                return label;
            }
        }

        public override ImageSource SmallImageSource
        {
            get {
                if (null == smallImage)
                {
                    ReadImages();
                }
                return smallImage;
            }
        }

        public override ImageSource LargeImageSource
        {
            get {
                if (null == largeImage)
                {
                    ReadImages();
                }
                return largeImage;
            }
        }

        public override bool IsLaunchable
        {
            get { return true; }
        }

        public override IList Children
        {
            get { return null; }
        }

        #endregion

        #region Methods

        public override bool Launch()
        {
            var proc = new Process();
            proc.StartInfo.FileName = path;
            proc.StartInfo.UseShellExecute = true;
            return proc.Start();
        }

        private void ReadImages()
        {
            if (!triedReadImages)
            {
                try {
                    triedReadImages = true;
                    iconCache.LoadIcon(Path, this);
                } catch (Exception) {
                }
            }
        }

        private void IconLoadedFromCache(IconCache.IconCache sender, IconCache.IconLoadedEventArgs args)
        {
            if (args.UserData == this)
            {
                sender.IconLoaded -= IconLoadedFromCache;

                smallImage = args.SmallIcon;
                largeImage = args.LargeIcon;
                OnPropertyChanged("SmallImageSource");
                OnPropertyChanged("LargeImageSource");

                if (args.IsImageFile)
                {
                    label = null;
                    OnPropertyChanged("Label");
                }
            }
        }

        #endregion
    }
}
